#!/bin/sh -eu
#
# Copyright 2008 Mattias Norrby
#
# This file is part of Test Dept..
#
# Test Dept. is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Test Dept. is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Test Dept..  If not, see <http://www.gnu.org/licenses/>.

create_main() {
  FILE="$1"
  HEADER_FILE="`basename $FILE .c`.h"
  cat <<FILE_HEAD
#include <test-dept.h>

typedef void (*test_dept_test_function)();
typedef void (*test_dept_prepost_function)();

typedef struct {
  test_dept_test_function function;
  char* name;
} test_dept_test_function_data;

FILE_HEAD
  sed -n -e '
  H; g; /}/{/^[^}]*}/s///;
      x;
      /^[^}]*[^A-Za-z0-9_*]*void[^A-Za-z0-9_*]*\([Tt]est[_]*[A-Za-z_0-9*][A-Za-z_0-9*]*\).*([^a-zA-Z_0-9*]*).*$/s//\1/p;
      /^[^}]*[^A-Za-z0-9_*]*void[^A-Za-z0-9_*]*\([Ss]et[Uu]p\)[^A-Za-z0-9_*]*([^A-Za-z0-9_*]*).*$/s//\1/p;
      /^[^}]*[^A-Za-z0-9_*]*void[^A-Za-z0-9_*]*\([Tt]ear[_]*[Dd]own\)[^A-Za-z0-9_*]*([^A-Za-z0-9_*]*).*$/s//\1/p;
      d;
      x; }
  ' $FILE | awk '
  BEGIN { test_functions[0];
          no_test_functions = 0;
          setup_function = "NULL";
          teardown_function = "NULL"; }
  /^[Ss]et[_]*[Uu]p$/ { setup_function = $1; next }
  /^[Tt]ear[_]*[Dd]own$/ { teardown_function = $1; next }
  { test_functions[no_test_functions] = $1;
    no_test_functions = no_test_functions + 1}
  END {
         if (setup_function != "NULL") {
           print "void " setup_function "();";
           setup_function = "&" setup_function;
         }
         if (teardown_function != "NULL") {
           print "void " teardown_function "();";
           teardown_function = "&" teardown_function;
         }
         for (x in test_functions)
           print "void " test_functions[x] "();";
         print "test_dept_prepost_function setup_function =  " setup_function ";" ;
         print "test_dept_prepost_function teardown_function = " teardown_function ";" ;
         print ""
         print "test_dept_test_function_data test_functions[] = {"
         for (x in test_functions)
           print "    {&" test_functions[x] ", \"" test_functions[x] "\"},";
         print "};";
         print "";
         print "int number_of_test_functions = " no_test_functions ";";
  }
  '
  cat <<FILE_TAIL

int main(int argc, char *argv[]) {
  if (argc == 1) {
    int i = 0;
    while (i < number_of_test_functions)
      printf("%s\n", test_functions[i++].name);
  }
  int test_no = 1;
  for (test_no; test_no < argc; test_no++) {
    char* test_fun_name = argv[test_no];
    int test_fun = 0;
    for (; test_fun < number_of_test_functions; test_fun++)
      if (0 == strcmp(test_fun_name, test_functions[test_fun].name))
        break;
    if (test_fun < 0 || test_fun >= number_of_test_functions) {
      fprintf(stderr, "No test with number %d!\n", test_fun);
      continue;
    }
    test_dept_test_function_data current = test_functions[test_fun];
    printf("%s:\n", current.name);
    fflush(stdout);
    if (setup_function)
      (*setup_function)();
    (*current.function)();
    if (teardown_function)
      (*teardown_function)();
  }
  return test_dept_test_failures;
}
FILE_TAIL
}

case "$#" in
  1) create_main $1
  ;;
  2) create_main $1 >$2
  ;;
  *) echo "Usage: $0 <file> [output file]"
  ;;
esac
